package com.android.htdvideoview;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;

import java.io.IOException;

public class InternalTextureView extends TextureView implements TextureView.SurfaceTextureListener {
    private static final String TAG = "HtdSimpleVideoView";

    private static SurfaceTexture sSurfaceTexture;
    private MediaPlayer mMediaPlayer;
    private MediaPlayer.OnPreparedListener mOnPreparedListener;
    private MediaPlayer.OnCompletionListener mOnCompletionListener;
    private MediaPlayer.OnErrorListener mOnErrorListener;
    private MediaPlayer.OnInfoListener mOnInfoListener;
    private Surface mSurface;
    private int mTargetState = STATE_IDLE;
    private int mCurrentState = STATE_IDLE;
    private static final int STATE_ERROR = -1;
    private static final int STATE_IDLE = 0;
    private static final int STATE_PREPARING = 1;
    private static final int STATE_PREPARED = 2;
    private static final int STATE_PLAYING = 3;
    private static final int STATE_PAUSED = 4;
    private static final int STATE_PLAYBACK_COMPLETED = 5;
    private int mBufferingPercent = 0;
    private boolean mLooping = false;
    private String mUrl;
    private Uri mUri;

    public InternalTextureView(Context context) {
        this(context, null);
    }

    public InternalTextureView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        setSurfaceTextureListener(this);
    }

    public void loadUrl(String url) {
        mUrl = url;
        mUri = null;
    }

    public void loadUri(Uri uri) {
        mUri = uri;
        mUrl = null;
    }

    public void openVideo() {
        mTargetState = STATE_PLAYING;
        try {
            mMediaPlayer = new MediaPlayer();
            if (mUrl != null) {
                mMediaPlayer.setDataSource(mUrl);
            } else {
                mMediaPlayer.setDataSource(getContext(), mUri);
            }
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setLooping(mLooping);
            mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
            mMediaPlayer.setOnPreparedListener(mPreparedListener);
            mMediaPlayer.setOnCompletionListener(mCompletionListener);
            mMediaPlayer.setOnErrorListener(mErrorListener);
            mMediaPlayer.setOnInfoListener(mOnInfoListener);
            mMediaPlayer.setSurface(mSurface);
            mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
            mMediaPlayer.setScreenOnWhilePlaying(true);
            mMediaPlayer.prepareAsync();
            mCurrentState = STATE_PREPARING;
            Log.d(TAG, "openVideo: 正在准备");
        } catch (IOException | IllegalArgumentException | SecurityException | IllegalStateException e) {
            e.printStackTrace();
            Log.d(TAG, "openVideo: 准备出错");
            mCurrentState = STATE_ERROR;
            mTargetState = STATE_ERROR;
            mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
        }
    }

    public void setLooping(boolean looping) {
        mLooping = looping;
        if (mMediaPlayer != null) {
            mMediaPlayer.setLooping(looping);
        }
    }

    public void stopPlayback() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
            Log.d(TAG, "stopPlayback: 已停止播放");
            mCurrentState = STATE_IDLE;
            mTargetState = STATE_IDLE;
//            mAudioManager.abandonAudioFocus(null);
        }
    }

   
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        if (sSurfaceTexture == null) {
            sSurfaceTexture = surface;
        } else {
            setSurfaceTexture(sSurfaceTexture);
        }
        if (mSurface == null) {
            mSurface = new Surface(surface);
        }
        if (mMediaPlayer != null) {
            mMediaPlayer.setSurface(mSurface);
        }
    }

   
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    }

   
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        release(true);
        return true;
    }

    private void release(boolean cleartargetstate) {
        if (mMediaPlayer != null) {
            mMediaPlayer.reset();
            mMediaPlayer.release();
            mMediaPlayer = null;
            Log.d(TAG, "release: 已释放");
            mCurrentState = STATE_IDLE;
            if (cleartargetstate) {
                mTargetState = STATE_IDLE;
            }
//            if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
//                mAudioManager.abandonAudioFocus(null);
//            }
        }
    }

   
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
       
        public void onBufferingUpdate(MediaPlayer mp, int percent) {
            mBufferingPercent = percent;
        }
    };
    private MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
       
        public void onPrepared(MediaPlayer mp) {
            Log.d(TAG, "onPrepared: 准备完成");
            mCurrentState = STATE_PREPARED;
            if (mOnPreparedListener != null) {
                mOnPreparedListener.onPrepared(mp);
            }
            mVideoWidth = mp.getVideoWidth();
            mVideoHeight = mp.getVideoHeight();

            if (mTargetState == STATE_PLAYING) {
                start();
            }
        }
    };

    MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
        public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
            mVideoWidth = mp.getVideoWidth();
            mVideoHeight = mp.getVideoHeight();
            Log.d(TAG, "onVideoSizeChanged() called with: mp = [" + mp + "], width = [" + width + "], height = [" + height + "]");
            if (mVideoWidth != 0 && mVideoHeight != 0) {
//                        requestLayout();
            }
        }
    };

    private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
        public void onCompletion(MediaPlayer mp) {
            Log.d(TAG, "onCompletion: 播放完成");
            mCurrentState = STATE_PLAYBACK_COMPLETED;
            mTargetState = STATE_PLAYBACK_COMPLETED;

            if (mOnCompletionListener != null) {
                mOnCompletionListener.onCompletion(mMediaPlayer);
            }
//                    if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
//                        mAudioManager.abandonAudioFocus(null);
//                    }
        }
    };
    private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() {
        public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
            Log.d(TAG, "onError: 发生错误");
            mCurrentState = STATE_ERROR;
            mTargetState = STATE_ERROR;
            if (mOnErrorListener != null) {
                if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) {
                    return true;
                }
            }
            return true;
        }
    };

    public void start() {
        if (mMediaPlayer != null) {
            mMediaPlayer.start();
            Log.d(TAG, "start: 正在播放");
            mCurrentState = STATE_PLAYING;
        }
        mTargetState = STATE_PLAYING;
    }

   
    public void pause() {
        if (isInPlaybackState()) {
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
                Log.d(TAG, "pause: 已暂停");
                mCurrentState = STATE_PAUSED;
            }
        }
        mTargetState = STATE_PAUSED;
    }

    private boolean isInPlaybackState() {
        Log.d(TAG, "isInPlaybackState: 当前状态" + mCurrentState);
        return (mMediaPlayer != null &&
                mCurrentState != STATE_ERROR &&
                mCurrentState != STATE_IDLE &&
                mCurrentState != STATE_PREPARING);
    }

   
    public int getDuration() {
        if (mMediaPlayer != null) {
            return mMediaPlayer.getDuration();
        }
        return 0;
    }

   
    public int getCurrentPosition() {
        if (mMediaPlayer != null) {
            return mMediaPlayer.getCurrentPosition();
        }
        return 0;
    }

   
    public void seekTo(int pos) {
        if (mMediaPlayer != null) {
            mMediaPlayer.seekTo(pos);
        }
    }

   
    public boolean isPlaying() {
        if (mMediaPlayer != null) {
            return mMediaPlayer.isPlaying();
        }
        return false;
    }

    public int getBufferPercentage() {
        return mBufferingPercent;
    }

    public void setOnPreparedListener(MediaPlayer.OnPreparedListener onPreparedListener) {
        mOnPreparedListener = onPreparedListener;
    }

    public void setOnCompletionListener(MediaPlayer.OnCompletionListener onCompletionListener) {
        mOnCompletionListener = onCompletionListener;
    }

    public void setOnErrorListener(MediaPlayer.OnErrorListener onErrorListener) {
        mOnErrorListener = onErrorListener;
    }

    public void setOnInfoListener(MediaPlayer.OnInfoListener listener) {
        mOnInfoListener = listener;
        if (mMediaPlayer != null) {
            mMediaPlayer.setOnInfoListener(listener);
        }
    }

    public void release() {
        if (mMediaPlayer != null) {
            mMediaPlayer.reset();
            mMediaPlayer.release();
        }
    }

   
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mIsReleaseOnDetached) {
            release();
        }
    }

    private boolean mIsReleaseOnDetached;

    public void releaseWhenDetached(boolean releaseOnDetached) {
        mIsReleaseOnDetached = releaseOnDetached;
    }

    private int mVideoWidth = 0;
    private int mVideoHeight = 0;

   
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
        //        + MeasureSpec.toString(heightMeasureSpec) + ")");

        int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
        int height = getDefaultSize(mVideoHeight, heightMeasureSpec);

        if (mVideoWidth > 0 && mVideoHeight > 0) {

            int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
            int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
            int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

            if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
                // 大小是固定的
                width = widthSpecSize;
                height = heightSpecSize;
                Log.d(this.getClass().getName(), "onMeasure: 宽度大小 = " + widthSpecSize + " 宽度测量模式 EXACTLY");
                Log.d(this.getClass().getName(), "onMeasure: 高度大小 = " + heightSpecSize + " 高度测量模式 EXACTLY");

                // 为了兼容性，我们根据宽高比调整大小
                if (mVideoWidth * height < width * mVideoHeight) {
                    Log.i("@@@", "图像太宽，正在校正");
                    width = height * mVideoWidth / mVideoHeight;
                } else if (mVideoWidth * height > width * mVideoHeight) {
                    Log.i("@@@", "图像太高，正在校正");
                    height = width * mVideoHeight / mVideoWidth;
                }
            } else if (widthSpecMode == MeasureSpec.EXACTLY) {
                Log.d(this.getClass().getName(), "onMeasure: 宽度大小 = " + widthSpecSize + " 宽度测量模式 EXACTLY");
                // 仅固定宽度，如果可能，调整高度以匹配宽高比
                width = widthSpecSize;
                height = width * mVideoHeight / mVideoWidth;
                if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
                    // 在约束内无法匹配宽高比
                    height = heightSpecSize;
                }
            } else if (heightSpecMode == MeasureSpec.EXACTLY) {
                Log.d(this.getClass().getName(), "onMeasure: 高度大小 = " + heightSpecSize + " 高度测量模式 EXACTLY");
                // 仅固定高度​​，如果可能，调整宽度以匹配宽高比
                height = heightSpecSize;
                width = height * mVideoWidth / mVideoHeight;
                if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
                    // 在约束内无法匹配宽高比
                    width = widthSpecSize;
                }
            } else {
                Log.d(this.getClass().getName(), "onMeasure: 宽度大小 = " + widthSpecSize + " 宽度测量模式 未指定");
                Log.d(this.getClass().getName(), "onMeasure: 高度大小 = " + heightSpecSize + " 高度测量模式 未指定");
                // 宽度和高度均未固定，请尝试使用实际的视频尺寸
                width = mVideoWidth;
                height = mVideoHeight;
                if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
                    // 太高，减小宽度和高度
                    height = heightSpecSize;
                    width = height * mVideoWidth / mVideoHeight;
                }
                if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
                    // 太宽，减小宽度和高度
                    width = widthSpecSize;
                    height = width * mVideoHeight / mVideoWidth;
                }
            }
        } else {
            // 尚无尺寸，仅采用指定的规格尺寸
        }
        setMeasuredDimension(width, height);
    }

    public void setVideoWidthHeight(int videoWidth, int videoHeight) {
        mVideoWidth = videoWidth;
        mVideoHeight = videoHeight;
        requestLayout();
    }
}
